package com.piao.utils;


import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.piao.common.ErrorEnum;
import com.piao.exception.DefinitionException;
import com.piao.vo.ParseResultVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.CookieStore;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 王浦伟
 * @version 1.0.0
 * @ClassName ParseUtils
 * @Description 解析工具类
 * @createTime 2024年07月31日 15:56
 */
public class ParseUtils {

    /**
     * 功能描述: 皮皮虾
     * @author 王浦伟
     * @param sourceUrl 来源URL
     * @createTime 2024/8/1 11:23
     */
    public static ParseResultVO pipix(String sourceUrl) throws Exception {
        // 创建实例并禁止自动重定向
        CloseableHttpClient client = HttpClientBuilder.create().disableRedirectHandling().build();
        CloseableHttpResponse response = null;
        // 视频地址
        String videoUrl = sourceUrl;
        // 判断是否为短链接
        if (sourceUrl.contains("/s/")) {
            // 短链接
            // 发送请求
            response = client.execute(new HttpGet(sourceUrl));
            if (response.getCode() != 302) {
                // 如果不是302跳转则返回报错
                throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "该链接非302跳转，无法解析");
            }
            // 获取重定向的地址
            videoUrl = response.getHeader("location").getValue();
        }
        // 视频id
        String videoId = videoUrl.substring(videoUrl.indexOf("/item/") + 6, videoUrl.indexOf("?"));
        if (StringUtils.isBlank(videoId)) {
            // 获取视频id失败
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "获取视频id失败");
        }
        response = client.execute(new HttpGet("https://is.snssdk.com/bds/cell/detail/?cell_type=1&aid=1319&app_name=super&cell_id=" + videoId));
        // 解析返回的json
        String respjsonStr = EntityUtils.toString(response.getEntity());
        if (response.getCode() != 200) {
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "请求失败： " + respjsonStr);
        }
        Gson gson = new Gson();
        JsonObject data = gson.fromJson(respjsonStr, JsonObject.class);
        if (data.get("status_code").getAsInt() != 0) {
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "解析失败： " + data.get("message"));
        }
        // 类型：1.图文 2.视频
        int type =  data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("item_type").getAsInt();
        List<String> atlasList = new ArrayList<>();
        String url = "";
        if (type == 1) {
            JsonArray atlasArray = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("note").getAsJsonObject().get("multi_image").getAsJsonArray();
            for (int i = 0; i < atlasArray.size(); i++) {
                atlasList.add(atlasArray.get(i).getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString());
            }
        } else if (type == 2) {
            // 无水印视频地址
            url = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("origin_video_download").getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString();
        }
        // 标题
        String title = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("content").getAsString();
        // 封面
        String cover = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("cover").getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString();
        // 作者
        String author = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("author").getAsJsonObject().get("name").getAsString();
        // 作者头像
        String avatar = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("author").getAsJsonObject().get("avatar").getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString();
        // 播放量
        long viewCount = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("stats").getAsJsonObject().get("view_count").getAsLong();
        // 点赞量
        long likeCount = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("stats").getAsJsonObject().get("like_count").getAsLong();
        // 评论量
        long commentCount = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("stats").getAsJsonObject().get("comment_count").getAsLong();
        // 收藏量 (收藏数量不显示)
        long collectCount = 0L;
        // 转发量
        long shareCount = data.get("data").getAsJsonObject().get("data").getAsJsonObject().get("item").getAsJsonObject().get("stats").getAsJsonObject().get("share_count").getAsLong();

        ParseResultVO parseResultVO = new ParseResultVO();
        parseResultVO.setType(0);
        if (type == 1) {
            parseResultVO.setType(2);
        } else if (type == 2) {
            parseResultVO.setType(1);
        }
        parseResultVO.setAtlasList(atlasList);
        parseResultVO.setUrl(url);
        parseResultVO.setTitle(title);
        parseResultVO.setCover(cover);
        parseResultVO.setAuthor(author);
        parseResultVO.setAvatar(avatar);
        parseResultVO.setViewCount(viewCount);
        parseResultVO.setLikeCount(likeCount);
        parseResultVO.setCommentCount(commentCount);
        parseResultVO.setCollectCount(collectCount);
        parseResultVO.setShareCount(shareCount);
        return parseResultVO;
    }

    /**
     * 功能描述: 抖音，有时候会失败，多试几次 （判断如果有SSRDataScript则重新请求）
     * @author 王浦伟
     * @param sourceUrl
     * @createTime 2024/8/2 14:50
     */
    public static ParseResultVO douyin(String sourceUrl) throws Exception {
        // 重试次数
        int retryNum = 0;
        // 创建实例并禁止自动重定向
        CloseableHttpClient client = HttpClientBuilder.create().disableRedirectHandling().build();
        CloseableHttpResponse response = null;
        // 视频地址
        String videoUrl = sourceUrl;
        // 判断是否为短链接
        if (sourceUrl.contains("v.douyin.com")) {
            // 短链接
            // 发送请求
            response = client.execute(new HttpGet(sourceUrl));
            if (response.getCode() != 302) {
                // 如果不是302跳转则返回报错
                throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "该链接非302跳转，无法解析");
            }
            // 获取重定向的地址
            videoUrl = response.getHeader("location").getValue();
        }
        // 视频id
        String videoId = videoUrl.substring(videoUrl.indexOf("/video/") + 7, videoUrl.lastIndexOf("/"));
        if (StringUtils.isBlank(videoId)) {
            // 获取视频id失败
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "获取视频id失败");
        }
        HttpGet httpGet = new HttpGet("https://m.douyin.com/share/video/" + videoId);
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36 Edg/127.0.0.0");
        String respStr = "";
        do {
            if (retryNum > 0) {
                Thread.sleep(500);
            }
            retryNum++;
            response = client.execute(httpGet);
            // 解析返回的json
            respStr = EntityUtils.toString(response.getEntity());
        } while (respStr.contains("SSRDataScript") && retryNum <= 10);
        // 错误重试过多
        if (respStr.contains("SSRDataScript") && retryNum > 10) {
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "请求次数过多，请稍后再试");
        }
        if (response.getCode() != 200) {
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "请求失败： " + respStr);
        }
        respStr = respStr.substring(respStr.indexOf("window._ROUTER_DATA = ") + 22, respStr.lastIndexOf("</script>"));
        if (StringUtils.isBlank(respStr) || respStr.charAt(0) != '{') {
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "解析失败： " + respStr);
        }
        Gson gson = new Gson();
        JsonObject data = gson.fromJson(respStr, JsonObject.class);
        // 类型：2.图集 4.视频
        int type = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("aweme_type").getAsInt();
        List<String> atlasList = new ArrayList<>();
        String url = "";
        if (type == 2) {
            JsonArray atlasArray = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("images").getAsJsonArray();
            for (int i = 0; i < atlasArray.size(); i++) {
                atlasList.add(atlasArray.get(i).getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsString());
            }
        } else if (type == 4) {
            // 无水印视频地址
            url = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("video").getAsJsonObject().get("play_addr").getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsString().replace("playwm", "play");
            // 但是需要访问一下这个地址
            response = client.execute(new HttpGet(url));
            // 获取重定向后的视频地址，否则前端下载视频时会有问题
            if (response.getCode() == 302) {
                url = response.getHeader("location").getValue();
            }
        }
        // 标题
        String title = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("desc").getAsString();
        // 封面
        String cover = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("video").getAsJsonObject().get("cover").getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsString();
        // 作者
        String author = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("author").getAsJsonObject().get("nickname").getAsString();
        // 作者头像
        String avatar = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("author").getAsJsonObject().get("avatar_thumb").getAsJsonObject().get("url_list").getAsJsonArray().get(0).getAsString();
        // 播放量 (抖音取出的播放量为0)
        long viewCount = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("statistics").getAsJsonObject().get("play_count").getAsLong();
        // 点赞量
        long likeCount = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("statistics").getAsJsonObject().get("digg_count").getAsLong();
        // 评论量
        long commentCount = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("statistics").getAsJsonObject().get("comment_count").getAsLong();
        // 收藏量
        long collectCount = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("statistics").getAsJsonObject().get("collect_count").getAsLong();
        // 转发量
        long shareCount = data.get("loaderData").getAsJsonObject().get("video_(id)/page").getAsJsonObject().get("videoInfoRes").getAsJsonObject().get("item_list").getAsJsonArray().get(0).getAsJsonObject().get("statistics").getAsJsonObject().get("share_count").getAsLong();

        ParseResultVO parseResultVO = new ParseResultVO();
        parseResultVO.setType(0);
        if (type == 2) {
            parseResultVO.setType(2);
        } else if (type == 4) {
            parseResultVO.setType(1);
        }
        parseResultVO.setAtlasList(atlasList);
        parseResultVO.setUrl(url);
        parseResultVO.setTitle(title);
        parseResultVO.setCover(cover);
        parseResultVO.setAuthor(author);
        parseResultVO.setAvatar(avatar);
        parseResultVO.setViewCount(viewCount);
        parseResultVO.setLikeCount(likeCount);
        parseResultVO.setCommentCount(commentCount);
        parseResultVO.setCollectCount(collectCount);
        parseResultVO.setShareCount(shareCount);
        return parseResultVO;
    }

    /**
     * 功能描述: 快手
     * @author 王浦伟
     * @param sourceUrl
     * @return com.piao.vo.ParseResultVO
     * @createTime 2024/8/2 14:52
     */
    public static ParseResultVO kuiashou(String sourceUrl) throws Exception {
        // 创建实例并禁止自动重定向
        CloseableHttpClient client = HttpClientBuilder.create().disableRedirectHandling().build();
        CloseableHttpResponse response = null;
        // 视频地址
        String videoUrl = sourceUrl;
        // 判断是否为短链接
        if (sourceUrl.contains("v.kuaishou.com")) {
            // 短链接
            // 发送请求
            response = client.execute(new HttpGet(sourceUrl));
            if (response.getCode() != 302) {
                // 如果不是302跳转则返回报错
                throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "该链接非302跳转，无法解析");
            }
            // 获取重定向的地址
            videoUrl = response.getHeader("location").getValue();
        }
        String videoId = videoUrl.substring(videoUrl.lastIndexOf("/") + 1, videoUrl.indexOf("?"));
        if (StringUtils.isBlank(videoId)) {
            // 获取视频id失败
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "获取视频id失败");
        }
        // 拼接参数
        Map<String, Object> params = new HashMap<>();
        params.put("env", "SHARE_VIEWER_ENV_TX_TRICK");
        params.put("h5Domain", "m.gifshow.com");
        params.put("photoId", videoId);
        params.put("isLongVideo", false);
        Gson gson = new Gson();

        HttpPost httpPost = new HttpPost("https://m.gifshow.com/rest/wd/photo/info?kpn=undefined&captchaToken=&__NS_sig3=");
        StringEntity stringEntity = new StringEntity(gson.toJson(params), ContentType.APPLICATION_JSON);
        httpPost.setEntity(stringEntity);
        httpPost.setHeader("Referer", videoUrl);
        httpPost.setHeader("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36 Edg/127.0.0.0");
        httpPost.setHeader("Cookie", "did=web_5cb3f9b2ea8d4e5197155a2ddbab7e46; didv=1722500846000");
        response = client.execute(httpPost);
        String respjsonStr = EntityUtils.toString(response.getEntity());
        if (response.getCode() != 200) {
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "请求失败： " + respjsonStr);
        }
        JsonObject data = gson.fromJson(respjsonStr, JsonObject.class);
        if (data.get("result").getAsInt() != 1) {
            throw new DefinitionException(ErrorEnum.INTERNAL_SERVER_ERROR.getErrorCode(), "解析失败： " + data.get("error_msg"));
        }
        // 类型：VIDEO=视频 HORIZONTAL_ATLAS=图集
        String type = data.get("photo").getAsJsonObject().get("photoType").getAsString();
        List<String> atlasList = new ArrayList<>();
        String url = "";
        if ("VIDEO".equals(type)) {
            // 无水印视频地址
            url = data.get("mp4Url").getAsString();
        } else if ("HORIZONTAL_ATLAS".equals(type)) {
            // 图集
            // 先获取CDN地址
            String cdnUrl = data.get("atlas").getAsJsonObject().get("cdn").getAsJsonArray().get(0).getAsString();
            // 获取图集URI
            JsonArray atlasUriList = data.get("atlas").getAsJsonObject().get("list").getAsJsonArray();
            for (int i = 0; i < atlasUriList.size(); i++) {
                atlasList.add("https://" + cdnUrl + atlasUriList.get(i).getAsString());
            }
        }
        // 标题
        String title = data.get("photo").getAsJsonObject().get("caption").getAsString();
        // 封面
        String cover = data.get("photo").getAsJsonObject().get("coverUrls").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString();
        // 作者
        String author = data.get("photo").getAsJsonObject().get("userName").getAsString();
        // 作者头像
        String avatar = data.get("photo").getAsJsonObject().get("headUrls").getAsJsonArray().get(0).getAsJsonObject().get("url").getAsString();
        // 播放量
        long viewCount = data.get("photo").getAsJsonObject().get("viewCount").getAsLong();
        // 点赞量
        long likeCount = data.get("photo").getAsJsonObject().get("likeCount") == null ? 0L : data.get("photo").getAsJsonObject().get("likeCount").getAsLong();
        // 评论量
        long commentCount = data.get("photo").getAsJsonObject().get("commentCount").getAsLong();
        // 收藏量
        long collectCount = data.get("counts").getAsJsonObject().get("collectionCount").getAsLong();
        // 转发量（可能是这个字段，不是很确定）
        long shareCount = data.get("counts").getAsJsonObject().get("followCount").getAsLong();

        ParseResultVO parseResultVO = new ParseResultVO();
        parseResultVO.setType(0);
        if ("HORIZONTAL_ATLAS".equals(type)) {
            parseResultVO.setType(2);
        } else if ("VIDEO".equals(type)) {
            parseResultVO.setType(1);
        }
        parseResultVO.setAtlasList(atlasList);
        parseResultVO.setUrl(url);
        parseResultVO.setTitle(title);
        parseResultVO.setCover(cover);
        parseResultVO.setAuthor(author);
        parseResultVO.setAvatar(avatar);
        parseResultVO.setViewCount(viewCount);
        parseResultVO.setLikeCount(likeCount);
        parseResultVO.setCommentCount(commentCount);
        parseResultVO.setCollectCount(collectCount);
        parseResultVO.setShareCount(shareCount);
        return parseResultVO;
    }
}